package com.lwlk.util.flow;

import java.util.function.Consumer;
import java.util.function.Function;

public final class Ref<T> {

    private T value;

    private Ref() {

    }

    private Ref(final T value) {

        this.value = value;
    }

    public static <T> Ref<T> of(final T value) {

        return new Ref<>(value);
    }

    public static <T> Ref<T> empty() {

        return new Ref<>(null);
    }

    public Ref<T> swap(final T value) {

        this.value = value;

        return this;
    }

    public Ref<T> shift(final T value) {

        final Ref<T> old = new Ref<>(this.value);

        swap(value);

        return old;
    }

    public <R> Ref<R> map(final Function<T, R> trans) {

        return isPresent() ? new Ref<R>(trans.apply(value)) : new Ref<>(null);
    }

    public <R> R flatmap(final Function<T, R> trans) {

        return isPresent() ? trans.apply(value) : null;
    }

    public boolean isPresent() {

        return value != null;
    }

    public void ifPresent(final Consumer<T> consumer) {

        if(isPresent()) consumer.accept(get());
    }

    public T get() {

        return value;
    }

    public T orElse(final T elseValue) {

        return isPresent() ? get() : elseValue;
    }
}
